package com.mtiiot.fsmanage.server;


import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.mtiiot.fsmanage.bean.common.ChartSeries;
import com.mtiiot.fsmanage.bean.common.TableDataInfo;
import com.mtiiot.fsmanage.utils.Contants;
import com.mtiiot.fsmanage.utils.TimeUtil;
import com.mtiiot.fscore.utils.StringUtil;
import com.mtiiot.fsmanage.bean.metadata.log.LogMetadata;
import com.mtiiot.fsmanage.bean.metadata.log.LogStatisticsData;
import com.mtiiot.fsmanage.bean.metadata.log.LogStatisticsGroup;
import com.mtiiot.fsmanage.core.dao.BaseElasticsearch;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.metrics.stats.InternalStats;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


@Service
@Transactional
public class LogServer{
    @Autowired
    private BaseElasticsearch baseElasticsearch;
    private static String INDEX = Contants.INDEX_METADATA;
    private static String TYPE = Contants.TYPE_METADATA_LOG;

    public Object logQuery(String sysName,String l1Name,String l2Name,String l3Name,String logLevel,String times,String queryKeyWord,int count, String sort) throws Exception {
        Client client=null;
        try{
            client=baseElasticsearch.getEsDataSource().getClient();
            BoolQueryBuilder bq=QueryBuilders.boolQuery();
            if(!StringUtil.isEmpty(logLevel)){
                if(!logLevel.equals("all")){
                    bq.must(QueryBuilders.termQuery("logLevel", logLevel));                 // Query
                }
            }
            if(!StringUtil.isEmpty(sysName)){
                bq.must(QueryBuilders.termQuery("sysName", sysName));                 // Query
            }
            if(!StringUtil.isEmpty(l1Name)){
                bq.must(QueryBuilders.termQuery("l1Name", l1Name));                 // Query
            }
            if(!StringUtil.isEmpty(l2Name)){
                bq.must(QueryBuilders.termQuery("l2Name", l2Name));                 // Query
            }
            if(!StringUtil.isEmpty(l3Name)){
                bq.must(QueryBuilders.termQuery("l3Name", l3Name));                 // Query
            }
            if(!StringUtil.isEmpty(queryKeyWord)){
                bq.must(QueryBuilders.queryStringQuery(queryKeyWord));
            }
            long[] l= TimeUtil.handleTimes(times);
            if(l!=null&&l.length>0){
                bq.must(QueryBuilders.rangeQuery("time").from(l[0]).to(l[1]));
            }
            QueryBuilder queryBuilder = bq;
            SortOrder sortOrder=null;
            if("desc".equals(sort)){
                sortOrder=SortOrder.DESC;
            }else{
                sortOrder=SortOrder.ASC;
            }
            SearchRequestBuilder srb = client.prepareSearch(INDEX)
                    .setTypes(TYPE)
                            //按时间降序号
                    .addSort("time", sortOrder)
                    .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                            // 设置查询数据的位置,分页用
                    .setFrom(0)
                            // 设置查询结果集的最大条数
                    .setSize(count)
                            // 设置是否按查询匹配度排序
                    .setExplain(true);
            // 最后就是返回搜索响应信息
            srb.setQuery(bq);

            SearchResponse response =srb.execute().actionGet();
            SearchHits searchHits = response.getHits();
            SearchHit[] hits = searchHits.getHits();
            TableDataInfo tdif=new TableDataInfo();
            tdif.setCount(searchHits.totalHits());
            List<LogMetadata> list=new ArrayList<LogMetadata>();
            for (SearchHit searchHit : hits) {
                Map<String, Object> sm = searchHit.sourceAsMap();
                LogMetadata lm=new LogMetadata();
                if(sm.get("sysId")==null){
                    lm.setSysId("-");
                }else{
                    lm.setSysId(sm.get("sysId").toString());
                }
                if(sm.get("sysName")==null){
                    lm.setSysName("-");
                }else{
                    lm.setSysName(sm.get("sysName").toString());
                }

                lm.setL1Name(sm.get("l1Name").toString());
                lm.setL2Name(sm.get("l2Name").toString());
                lm.setL3Name(sm.get("l3Name").toString());
                lm.setYear(Integer.parseInt(sm.get("year").toString()));
                lm.setMonth(Integer.parseInt(sm.get("month").toString()));
                lm.setDay(Integer.parseInt(sm.get("day").toString()));
                long t=(Long)sm.get("time");
                lm.setTime(new Date(t));
                lm.setShowTime(sm.get("showTime").toString());
                lm.setKeyValue(sm.get("keyValue").toString());
                lm.setLogLevel(sm.get("logLevel").toString());
                lm.setMessage(sm.get("message").toString());
                lm.setHost(sm.get("host").toString());
                lm.setRequestType(sm.get("requestType").toString());
                lm.setRequestSize(Double.parseDouble(sm.get("requestSize").toString()));
                list.add(lm);
            }
            tdif.setObject(list);
            return tdif;
        }finally {
            if(client!=null){
                baseElasticsearch.getEsDataSource().releaseClient(client);
            }
        }
    }

    public Object logStatistics(String sysName,String l1Name,String l2Name,String l3Name,String logLevel,String times) throws Exception {
        Client client=null;
        try{
            client=baseElasticsearch.getEsDataSource().getClient();
            BoolQueryBuilder bq=QueryBuilders.boolQuery();
            if(!StringUtil.isEmpty(logLevel)){
                if(!logLevel.equals("all")){
                    bq.must(QueryBuilders.termQuery("logLevel", logLevel));
                }
            }
            if(!StringUtil.isEmpty(sysName)){
                bq.must(QueryBuilders.termQuery("sysName", sysName));
            }
            if(!StringUtil.isEmpty(l1Name)){
                bq.must(QueryBuilders.termQuery("l1Name", l1Name));
            }
            if(!StringUtil.isEmpty(l2Name)){
                bq.must(QueryBuilders.termQuery("l2Name", l2Name));
            }
            if(!StringUtil.isEmpty(l3Name)){
                bq.must(QueryBuilders.termQuery("l3Name", l3Name));
            }
            long[] l= TimeUtil.handleTimes(times);
            if(l!=null&&l.length>0){
                bq.must(QueryBuilders.rangeQuery("time").from(l[0]).to(l[1]));
            }
            QueryBuilder queryBuilder = bq;


            SearchRequestBuilder srb = client.prepareSearch(INDEX)
                    .setTypes(TYPE)
                            //按时间降序号
                            // .addSort("time", SortOrder.DESC)
                    .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                            // 设置查询数据的位置,分页用
                            //.setFrom(0)
                            // 设置查询结果集的最大条数
                            //.setSize(500)
                            // 设置是否按查询匹配度排序
                    .setExplain(true);
            // 最后就是返回搜索响应信息
            srb.setQuery(bq);

            String aggTremName="tremAgg";
            String aggStatsName="statsAgg";
            String statsType=null;
            if(StringUtil.isEmpty(sysName)){
                //统计系统级别的
                srb.addAggregation(AggregationBuilders.terms(aggTremName).field("sysName").subAggregation(AggregationBuilders.stats(aggStatsName).field("requestSize")));
                statsType="sysName";
            }else{
                if(StringUtil.isEmpty(l1Name)){
                    //统计l1级别的
                    srb.addAggregation(AggregationBuilders.terms(aggTremName).field("l1Name").subAggregation(AggregationBuilders.stats(aggStatsName).field("requestSize")));
                    statsType="l1";
                }else{
                    if(StringUtil.isEmpty(l2Name)){
                        //统计l2级别的
                        srb.addAggregation(AggregationBuilders.terms(aggTremName).field("l2Name").subAggregation(AggregationBuilders.stats(aggStatsName).field("requestSize")));
                        statsType="l2";
                    }else{
                        //统计l3级别的
                        srb.addAggregation(AggregationBuilders.terms(aggTremName).field("l3Name").subAggregation(AggregationBuilders.stats(aggStatsName).field("requestSize")));
                        statsType="l3";
                    }
                }
            }
            SearchResponse response =srb.execute().actionGet();
            Aggregations sysAggr=response.getAggregations();
            Terms sysNameAgg=sysAggr.get(aggTremName);
            List<Terms.Bucket> list=sysNameAgg.getBuckets();
            LogStatisticsGroup lsg=new LogStatisticsGroup();
            List<LogStatisticsData> lsds=new ArrayList<LogStatisticsData>();
            String[] chartCategories=new String[list.size()];
            Long[] requestCountArr=new Long[list.size()];
            Double[] requestSizeArr=new Double[list.size()];
            LogStatisticsData lsd=null;
            int i=0;
            for(Terms.Bucket tb:list){
                Aggregations statsAggr=tb.getAggregations();
                InternalStats is = statsAggr.get(aggStatsName);
                String keyValue=tb.getKey().toString();
                chartCategories[i]=keyValue;
                requestCountArr[i]=is.getCount();
                requestSizeArr[i]=is.getSum();
                lsd=new LogStatisticsData();
                if("sysName".equals(statsType)){
                    lsd.setSysName(keyValue);
                }else if("l1".equals(statsType)){
                    lsd.setSysName(sysName);
                    lsd.setL1Name(keyValue);
                }else if("l2".equals(statsType)){
                    lsd.setSysName(sysName);
                    lsd.setL1Name(l1Name);
                    lsd.setL2Name(keyValue);
                }else if("l3".equals(statsType)){
                    lsd.setSysName(sysName);
                    lsd.setL1Name(l1Name);
                    lsd.setL2Name(l2Name);
                    lsd.setL3Name(keyValue);
                }
                lsd.setLogLevel(logLevel);
                lsd.setRequestCount(is.getCount());
                lsd.setRequestSize(is.getSum());
                lsds.add(lsd);
                i++;
            }
            lsg.setLsds(lsds);
            lsg.setChartCategories(chartCategories);
            List<ChartSeries> css=new ArrayList<ChartSeries>();
            if(requestCountArr.length>0){
                ChartSeries cs1=new ChartSeries();
                cs1.setName("请求");
                cs1.setData(requestCountArr);
                css.add(cs1);
                cs1=new ChartSeries();
                cs1.setName("流量");
                cs1.setData(requestSizeArr);
                css.add(cs1);
            }
            lsg.setCss(css);
            return lsg;
        }finally {
            if(client!=null){
                baseElasticsearch.getEsDataSource().releaseClient(client);
            }
        }
    }
}
